package ko.util;

import ko.KTweener;

public class KEquations {

	public static void init() {
		KTweener.registerTransition("easenone",			new easeNone());
		KTweener.registerTransition("linear",			new easeNone());		// mx.transitions.easing.None.easeNone
		
		KTweener.registerTransition("easeinquad",		new easeInQuad());	// mx.transitions.easing.Regular.easeIn
		KTweener.registerTransition("easeoutquad",		new easeOutQuad());	// mx.transitions.easing.Regular.easeOut
		KTweener.registerTransition("easeinoutquad",	new easeInOutQuad());	// mx.transitions.easing.Regular.easeInOut
		KTweener.registerTransition("easeoutinquad",	new easeOutInQuad());
		
		KTweener.registerTransition("easeincubic",		new easeInCubic());
		KTweener.registerTransition("easeoutcubic",		new easeOutCubic());
		KTweener.registerTransition("easeinoutcubic",	new easeInOutCubic());
		KTweener.registerTransition("easeoutincubic",	new easeOutInCubic());
		
		KTweener.registerTransition("easeinquart",		new easeInQuart());
		KTweener.registerTransition("easeoutquart",		new easeOutQuart());
		KTweener.registerTransition("easeinoutquart",	new easeInOutQuart());
		KTweener.registerTransition("easeoutinquart",	new easeOutInQuart());
		
		KTweener.registerTransition("easeinquint",		new easeInQuint());
		KTweener.registerTransition("easeoutquint",		new easeOutQuint());
		KTweener.registerTransition("easeinoutquint",	new easeInOutQuint());
		KTweener.registerTransition("easeoutinquint",	new easeOutInQuint());
		
		KTweener.registerTransition("easeinsine",		new easeInSine());
		KTweener.registerTransition("easeoutsine",		new easeOutSine());
		KTweener.registerTransition("easeinoutsine",	new easeInOutSine());
		KTweener.registerTransition("easeoutinsine",	new easeOutInSine());
		
		KTweener.registerTransition("easeincirc",		new easeInCirc());
		KTweener.registerTransition("easeoutcirc",		new easeOutCirc());
		KTweener.registerTransition("easeinoutcirc",	new easeInOutCirc());
		KTweener.registerTransition("easeoutincirc",	new easeOutInCirc());
		
		KTweener.registerTransition("easeinexpo",		new easeInExpo());		// mx.transitions.easing.Strong.easeIn
		KTweener.registerTransition("easeoutexpo", 		new easeOutExpo());		// mx.transitions.easing.Strong.easeOut
		KTweener.registerTransition("easeinoutexpo", 	new easeInOutExpo());		// mx.transitions.easing.Strong.easeInOut
		KTweener.registerTransition("easeoutinexpo", 	new easeOutInExpo());
		
		KTweener.registerTransition("easeinelastic", 	new easeInElastic());		// mx.transitions.easing.Elastic.easeIn
		KTweener.registerTransition("easeoutelastic", 	new easeOutElastic());	// mx.transitions.easing.Elastic.easeOut
		KTweener.registerTransition("easeinoutelastic", new easeInOutElastic());	// mx.transitions.easing.Elastic.easeInOut
		KTweener.registerTransition("easeoutinelastic", new easeOutInElastic());
		
		KTweener.registerTransition("easeinback", 		new easeInBack());		// mx.transitions.easing.Back.easeIn
		KTweener.registerTransition("easeoutback", 		new easeOutBack());		// mx.transitions.easing.Back.easeOut
		KTweener.registerTransition("easeinoutback", 	new easeInOutBack());		// mx.transitions.easing.Back.easeInOut
		KTweener.registerTransition("easeoutinback", 	new easeOutInBack());
		
		KTweener.registerTransition("easeinbounce", 	new easeInBounce());		// mx.transitions.easing.Bounce.easeIn
		KTweener.registerTransition("easeoutbounce", 	new easeOutBounce());		// mx.transitions.easing.Bounce.easeOut
		KTweener.registerTransition("easeinoutbounce", 	new easeInOutBounce());	// mx.transitions.easing.Bounce.easeInOut
		KTweener.registerTransition("easeoutinbounce", 	new easeOutInBounce());
	}
	
	
}

class easeNone implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		return c*t/d + b;
	}
}

class easeInQuad implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		return c*(t/=d)*t + b;
	}
}

class easeOutQuad implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		return -c *(t/=d)*(t-2) + b;
	}
}

class easeInOutQuad implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		if ((t/=d/2) < 1) return c/2*t*t + b;
		return -c/2 * ((--t)*(t-2) - 1) + b;
	}
}

class easeOutInQuad implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		TransitionParam p_params = (TransitionParam) args[4];
		if (t < d/2) return Float.parseFloat(new easeOutQuad().function(t*2, b, c/2, d, p_params).toString());
		return Float.parseFloat(new easeInQuad().function((t*2)-d, b+c/2, c/2, d, p_params).toString());
	}
}

class easeInCubic implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		return c*(t/=d)*t*t + b;
	}
}

class easeOutCubic implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		return c*((t=t/d-1)*t*t + 1) + b;
	}
}

class easeInOutCubic implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		if ((t/=d/2) < 1) return c/2*t*t*t + b;
		return c/2*((t-=2)*t*t + 2) + b;
	}
}

class easeOutInCubic implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		TransitionParam p_params = (TransitionParam) args[4];
		if (t < d/2) return Float.parseFloat(new easeOutCubic().function(t*2, b, c/2, d, p_params).toString());
		return Float.parseFloat(new easeInCubic().function((t*2)-d, b+c/2, c/2, d, p_params).toString());
	}
}

class easeInQuart implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		return c*(t/=d)*t*t*t + b;
	}
}

class easeOutQuart implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		return -c * ((t=t/d-1)*t*t*t - 1) + b;
	}
}

class easeInOutQuart implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
		return -c/2 * ((t-=2)*t*t*t - 2) + b;
	}
}

class easeOutInQuart implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		TransitionParam p_params = (TransitionParam) args[4];
		if (t < d/2) return Float.parseFloat(new easeOutQuart().function(t*2, b, c/2, d, p_params).toString());
		return Float.parseFloat(new easeInQuart().function((t*2)-d, b+c/2, c/2, d, p_params).toString());
	}
}

class easeInQuint implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		return c*(t/=d)*t*t*t*t + b;
	}
}

class easeOutQuint implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		return c*((t=t/d-1)*t*t*t*t + 1) + b;
	}
}

class easeInOutQuint implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
		return c/2*((t-=2)*t*t*t*t + 2) + b;
	}
}

class easeOutInQuint implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		TransitionParam p_params = (TransitionParam) args[4];
		if (t < d/2) return Float.parseFloat(new easeOutQuint().function(t*2, b, c/2, d, p_params).toString());
		return Float.parseFloat(new easeInQuint().function((t*2)-d, b+c/2, c/2, d, p_params).toString());
	}
}

class easeInSine implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
	}
}

class easeOutSine implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		return c * Math.sin(t/d * (Math.PI/2)) + b;
	}
}

class easeInOutSine implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
	}
}

class easeOutInSine implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		TransitionParam p_params = (TransitionParam) args[4];
		if (t < d/2) return Float.parseFloat(new easeOutSine().function(t*2, b, c/2, d, p_params).toString());
		return Float.parseFloat(new easeInSine().function((t*2)-d, b+c/2, c/2, d, p_params).toString());
	}
}

class easeInExpo implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b - c * 0.001f;
	}
}

class easeOutExpo implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		return (t==d) ? b+c : c * 1.001f * (-Math.pow(2, -10 * t/d) + 1) + b;
	}
}

class easeInOutExpo implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		if (t==0) return b;
		if (t==d) return b+c;
		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b - c * 0.0005f;
		return c/2 * 1.0005f * (-Math.pow(2, -10 * --t) + 2) + b;
	}
}

class easeOutInExpo implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		TransitionParam p_params = (TransitionParam) args[4];
		if (t < d/2) return Float.parseFloat(new easeOutExpo().function(t*2, b, c/2, d, p_params).toString());
		return Float.parseFloat(new easeInExpo().function((t*2)-d, b+c/2, c/2, d, p_params).toString());
	}
}

class easeInCirc implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
	}
}

class easeOutCirc implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
	}
}

class easeInOutCirc implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
	}
}

class easeOutInCirc implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		TransitionParam p_params = (TransitionParam) args[4];
		if (t < d/2) return Float.parseFloat(new easeOutCirc().function(t*2, b, c/2, d, p_params).toString());
		return Float.parseFloat(new easeInCirc().function((t*2)-d, b+c/2, c/2, d, p_params).toString());
	}
}

class easeInElastic implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		TransitionParam p_params = (TransitionParam) args[4];
		if (t==0) return b;
		if ((t/=d)==1) return b+c;
		float p = (float) ((p_params == null) || Float.isNaN(p_params.period) ? d*0.3f : p_params.period);
		float s;
		float a = (p_params == null) || Float.isNaN(p_params.amplitude) ? 0 : p_params.amplitude;
		if (Float.isNaN(a) || a <= Math.abs(c)) {
			a = c;
			s = p/4;
		} else {
			s = (float) (p/(2*Math.PI) * Math.asin(c/a));
		}
		return (float)-(a*Math.pow(2,10*(t-=1)) * Math.sin((t*d-s)*(2*Math.PI)/p )) + b;
	}
}

class easeOutElastic implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		TransitionParam p_params = (TransitionParam) args[4];
		if (t==0) return b;
		if ((t/=d)==1) return b+c;
		float p = (float) ((p_params == null) || Float.isNaN(p_params.period) ? d * 0.3f : p_params.period);
		float s;
		float a = (p_params == null) || Float.isNaN(p_params.amplitude) ? 0 : p_params.amplitude;
		if (Float.isNaN(a) || a <= Math.abs(c)) {
			a = c;
			s = p/4;
		} else {
			s = (float) (p/(2*Math.PI) * Math.asin (c/a));
		}
		return (a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b);
	}
}

class easeInOutElastic implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		TransitionParam p_params = (TransitionParam) args[4];
		if (t==0) return b;
		if ((t/=d/2)==2) return b+c;
		float p = (float) ((p_params == null) || Float.isNaN(p_params.period) ? d*(0.3f*1.5f) : p_params.period);
		float s;
		float a = (p_params == null) || Float.isNaN(p_params.amplitude) ? 0.0f : p_params.amplitude;
		
		if (Float.isNaN(a) || a <= Math.abs(c)) {
			a = c;
			s = p/4;
		} else {
			s = (float) (p/(2*Math.PI) * Math.asin (c/a));
		}
		if (t < 1) return -0.5f*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*0.5f + c + b;
	}
}

class easeOutInElastic implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		TransitionParam p_params = (TransitionParam) args[4];
		if (t < d/2) return Float.parseFloat(new easeOutElastic().function(t*2, b, c/2 , d, p_params).toString());
		return Float.parseFloat(new easeInElastic().function((t*2)-d, b+c/2, c/2, d, p_params).toString());
	}
}

class easeInBack implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		TransitionParam p_params = (TransitionParam) args[4];
		float s = (p_params == null) || Float.isNaN(p_params.overshoot) ? 1.70158f : p_params.overshoot;
		return c*(t/=d)*t*((s+1)*t - s) + b;
	}
}

class easeOutBack implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		TransitionParam p_params = (TransitionParam) args[4];
		float s = (p_params == null) || Float.isNaN(p_params.overshoot) ? 1.70158f : p_params.overshoot;
		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
	}
}

class easeInOutBack implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		TransitionParam p_params = (TransitionParam) args[4];
		float s = (p_params == null) || Float.isNaN(p_params.overshoot) ? 1.70158f : p_params.overshoot;
		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525f))+1)*t - s)) + b;
		return c/2*((t-=2)*t*(((s*=(1.525f))+1)*t + s) + 2) + b;
	}
}

class easeOutInBack implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		TransitionParam p_params = (TransitionParam) args[4];
		if (t < d/2) return Float.parseFloat(new easeOutBack().function(t*2, b, c/2, d, p_params).toString());
		return Float.parseFloat(new easeInBack().function((t*2)-d, b+c/2, c/2, d, p_params).toString());
	}
}

class easeInBounce implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		return c - Float.parseFloat(new easeOutBounce().function(d-t, 0, c, d).toString()) + b;
	}
}

class easeOutBounce implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()) ,b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		if ((t/=d) < (1/2.75)) {
			return c*(7.5625*t*t) + b;
		} else if (t < (2/2.75)) {
			return c*(7.5625*(t-=(1.5/2.75))*t + 0.75f) + b;
		} else if (t < (2.5/2.75)) {
			return c*(7.5625*(t-=(2.25/2.75))*t + 0.9375f) + b;
		} else {
			return c*(7.5625*(t-=(2.625/2.75))*t + 0.984375) + b;
		}
	}
}

class easeInOutBounce implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		if (t < d/2) return Float.parseFloat((new easeInBounce().function(t*2, 0.0f, c, d)).toString()) * 0.5f + b;
		else return Float.parseFloat(new easeOutBounce().function(t*2-d, 0.0f, c, d).toString()) * 0.5f + c*0.5f + b;
	}
}

class easeOutInBounce implements IFunction{
	public Object function(Object... args) {
		float t = Float.parseFloat(args[0].toString()),b = Float.parseFloat(args[1].toString()),c = Float.parseFloat(args[2].toString()),d = Float.parseFloat(args[3].toString());
		TransitionParam p_params = (TransitionParam) args[4];
		if (t < d/2) return Float.parseFloat((new easeOutBounce().function(t*2, b, c/2, d, p_params).toString()));
		return Float.parseFloat((new easeInBounce().function((t*2)-d, b+c/2, c/2, d, p_params).toString()));
	}
}
